package com.scheduling.schedule.algorithm.impl;

import com.scheduling.machine.entity.Machine;
import com.scheduling.order.entity.Order;
import com.scheduling.product.entity.Operation;
import com.scheduling.schedule.algorithm.ScheduleAlgorithm;
import com.scheduling.schedule.dto.ScheduleResult;
import com.scheduling.schedule.entity.ProductionTask;
import com.scheduling.schedule.entity.ScheduleDetail;
import com.scheduling.schedule.entity.Tuple2;
import com.scheduling.schedule.entity.WorkOrder;
import com.scheduling.schedule.enums.ScheduleAlgorithmType;
import com.scheduling.schedule.service.MachineLoadService;
import com.scheduling.schedule.service.OperationScheduleService;
import com.scheduling.schedule.service.ScheduleDataService;
import com.scheduling.schedule.service.WorkOrderGenerationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 关键路径法结合最短处理时间优先算法 - 基于CombineAlgorithm的正确时间管理
 * <p>
 * 核心特性：
 * 1. 使用MultiValueMap管理机器空闲时间段
 * 2. 实现正确的工序依赖拓扑排序
 * 3. 关键路径法(CPM)分析任务的关键性
 * 4. 最短处理时间优先(SPT)优化调度顺序
 * 5. 综合考虑紧急度、处理时间和关键路径
 * <p>
 * 算法策略：
 * - 关键路径优先：识别影响整体完工时间的关键任务
 * - SPT优化：在同等关键度下优先处理短时间任务
 * - 动态调整：根据实时机器负荷调整调度策略
 * <p>
 * 完整流程：
 * 1. 输入：订单列表
 * 2. 订单 → 紧急优先工单生成
 * 3. 工单 → 关键路径分析和SPT优化任务排产
 * 4. 输出：完整排产结果
 *
 * @author 开发团队
 */
@Slf4j
@Component("CRITICAL_PATH_SPT")
@RequiredArgsConstructor
public class CriticalPathSptAlgorithm implements ScheduleAlgorithm {

    private final WorkOrderGenerationService workOrderGenerationService;
    private final MachineLoadService machineLoadService;
    private final ScheduleDataService scheduleDataService;
    private final OperationScheduleService operationScheduleService;

    /**
     * 任务信息类 - 支持关键路径和SPT分析的任务信息
     */
    private static class TaskInfo {
        private WorkOrder workOrder;
        private List<Operation> operations;
        private int totalProcessingTime;
        private LocalDateTime dueDate;
        private int priority;
        private double criticalRatio;       // 关键比率 (剩余时间/剩余工作时间)
        private double urgencyScore;        // 紧急度评分
        private double sptScore;           // 最短处理时间评分
        private double criticalPathScore;   // 关键路径评分
        private double compositeScore;      // 综合评分

        public TaskInfo(WorkOrder workOrder, List<Operation> operations) {
            this.workOrder = workOrder;
            this.operations = operations;
            this.dueDate = workOrder.getPlanEndTime();
            this.priority = workOrder.getPriority() != null ? workOrder.getPriority() : 5;
            this.totalProcessingTime = calculateTotalProcessingTime(operations, workOrder.getQuantity());
        }

        private int calculateTotalProcessingTime(List<Operation> operations, Integer quantity) {
            int qty = quantity != null ? quantity : 1;
            return operations.stream()
                    .mapToInt(op -> (op.getStandardTime() != null ? op.getStandardTime() : 60) * qty)
                    .sum();
        }

        // Getters and Setters
        public WorkOrder getWorkOrder() {
            return workOrder;
        }

        public List<Operation> getOperations() {
            return operations;
        }

        public int getTotalProcessingTime() {
            return totalProcessingTime;
        }

        public LocalDateTime getDueDate() {
            return dueDate;
        }

        public int getPriority() {
            return priority;
        }

        public double getCriticalRatio() {
            return criticalRatio;
        }

        public void setCriticalRatio(double criticalRatio) {
            this.criticalRatio = criticalRatio;
        }

        public double getUrgencyScore() {
            return urgencyScore;
        }

        public void setUrgencyScore(double urgencyScore) {
            this.urgencyScore = urgencyScore;
        }

        public double getSptScore() {
            return sptScore;
        }

        public void setSptScore(double sptScore) {
            this.sptScore = sptScore;
        }

        public double getCriticalPathScore() {
            return criticalPathScore;
        }

        public void setCriticalPathScore(double criticalPathScore) {
            this.criticalPathScore = criticalPathScore;
        }

        public double getCompositeScore() {
            return compositeScore;
        }

        public void setCompositeScore(double compositeScore) {
            this.compositeScore = compositeScore;
        }
    }

    @Override
    public ScheduleResult schedule(List<Order> orders, LocalDateTime scheduleStartTime) {
        log.info("开始执行关键路径法+SPT排产算法，订单数量: {}", orders.size());

        long startTime = System.currentTimeMillis();
        ScheduleResult result = new ScheduleResult();

        try {
            if (orders.isEmpty()) {
                throw new IllegalArgumentException("订单列表不能为空");
            }

            // ========== 第一阶段：订单 → 工单生成 ==========
            List<WorkOrder> workOrders = generateWorkOrders(orders, scheduleStartTime);
            log.info("第一阶段完成：生成了 {} 个工单", workOrders.size());

            // ========== 第二阶段：工单 → 关键路径+SPT任务排产 ==========
            List<ProductionTask> productionTasks = generateProductionTasks(workOrders, scheduleStartTime);
            log.info("第二阶段完成：生成了 {} 个生产任务", productionTasks.size());

            // ========== 第三阶段：生成排产详情 ==========
            List<ScheduleDetail> scheduleDetails = generateScheduleDetails(productionTasks);

            // ========== 计算统计信息 ==========
            LocalDateTime scheduleEndTime = calculateScheduleEndTime(productionTasks);
            BigDecimal totalUtilization = scheduleDataService.calculateTotalUtilization(productionTasks,
                    scheduleStartTime, scheduleEndTime);

            // ========== 封装结果 ==========
            result.setSuccess(true);
            result.setScheduleStartTime(scheduleStartTime);
            result.setScheduleEndTime(scheduleEndTime);
            result.setTotalUtilization(totalUtilization);
            result.setGeneratedWorkOrders(workOrders);
            result.setProductionTasks(productionTasks);
            result.setScheduleDetails(scheduleDetails);
            result.setAlgorithmType(getAlgorithmType());
            result.setAlgorithmDescription(getDescription());
            result.setTotalWorkOrders(workOrders.size());
            result.setTotalTasks(productionTasks.size());
            result.setTotalMachines(calculateMachineCount(productionTasks));
            result.setExecutionTimeMs(System.currentTimeMillis() - startTime);

            log.info("关键路径法+SPT排产算法执行完成，工单: {}, 任务: {}, 设备利用率: {}%, 执行耗时: {}ms",
                    workOrders.size(), productionTasks.size(), totalUtilization, result.getExecutionTimeMs());

        } catch (Exception e) {
            log.error("关键路径法+SPT排产算法执行失败", e);
            result.setSuccess(false);
            result.setErrorMessage("算法执行失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public String getAlgorithmType() {
        return ScheduleAlgorithmType.CRITICAL_PATH_SPT.getCode();
    }

    @Override
    public String getDescription() {
        return ScheduleAlgorithmType.CRITICAL_PATH_SPT.getDescription();
    }

    @Override
    public List<WorkOrder> generateWorkOrders(List<Order> orders, LocalDateTime scheduleStartTime) {
        log.info("关键路径工单生成（紧急优先策略）");

        // 使用紧急优先策略生成工单
        List<WorkOrder> workOrders = workOrderGenerationService.generateUrgentPriorityWorkOrders(orders,
                scheduleStartTime);

        // 关键路径预排序：按截止时间和优先级排序
        workOrders.sort((wo1, wo2) -> {
            // 1. 按优先级排序（数字越小优先级越高）
            int priorityCompare = Integer.compare(
                    wo1.getPriority() != null ? wo1.getPriority() : 999,
                    wo2.getPriority() != null ? wo2.getPriority() : 999
            );
            if (priorityCompare != 0) {
                return priorityCompare;
            }

            // 2. 按计划结束时间排序（截止时间早的优先）
            if (wo1.getPlanEndTime() != null && wo2.getPlanEndTime() != null) {
                int dueDateCompare = wo1.getPlanEndTime().compareTo(wo2.getPlanEndTime());
                if (dueDateCompare != 0) {
                    return dueDateCompare;
                }
            }

            // 3. 按工单ID排序（确保稳定性）
            return wo1.getWorkOrderId().compareTo(wo2.getWorkOrderId());
        });

        log.info("关键路径工单生成完成，总数: {}", workOrders.size());
        return workOrders;
    }

    @Override
    public List<ProductionTask> generateProductionTasks(List<WorkOrder> workOrders, LocalDateTime scheduleStartTime) {
        log.info("执行关键路径+SPT任务优化");

        // 获取机器空闲时间表（使用CombineAlgorithm的高级时间管理）
        MultiValueMap<String, Tuple2<LocalDateTime, LocalDateTime>> machineAvailableTime =
                getMachineAvailableTime(scheduleStartTime);

        // 构建任务信息
        List<TaskInfo> taskInfos = buildTaskInfos(workOrders);
        log.debug("构建了 {} 个任务信息", taskInfos.size());

        // 计算关键路径和SPT评分
        calculateCriticalPathAndSPT(taskInfos, scheduleStartTime);

        // 执行混合调度策略
        List<ProductionTask> allTasks = executeHybridScheduling(taskInfos, machineAvailableTime, scheduleStartTime);

        log.info("关键路径+SPT优化完成，总任务数: {}", allTasks.size());
        return allTasks;
    }

    /**
     * 构建任务信息列表
     */
    private List<TaskInfo> buildTaskInfos(List<WorkOrder> workOrders) {
        List<TaskInfo> taskInfos = new ArrayList<>();

        for (WorkOrder workOrder : workOrders) {
            try {
                List<Operation> operations = scheduleDataService.getOperationsByProductId(workOrder.getProductId());
                operationScheduleService.sortOperations(operations); // 确保工序依赖正确

                if (!operations.isEmpty()) {
                    TaskInfo taskInfo = new TaskInfo(workOrder, operations);
                    taskInfos.add(taskInfo);
                }
            } catch (Exception e) {
                log.error("为工单 {} 构建任务信息失败", workOrder.getWorkOrderId(), e);
            }
        }

        return taskInfos;
    }

    /**
     * 计算关键路径和SPT评分
     */
    private void calculateCriticalPathAndSPT(List<TaskInfo> tasks, LocalDateTime scheduleStartTime) {
        log.debug("计算关键路径和SPT评分");

        // 找出最大处理时间（用于SPT评分标准化）
        int maxProcessingTime = tasks.stream()
                .mapToInt(TaskInfo::getTotalProcessingTime)
                .max()
                .orElse(1);

        for (TaskInfo task : tasks) {
            // 1. 计算关键比率
            if (task.getDueDate() != null) {
                long remainingMinutes = Duration.between(scheduleStartTime, task.getDueDate()).toMinutes();
                if (remainingMinutes > 0) {
                    task.setCriticalRatio((double) remainingMinutes / task.getTotalProcessingTime());
                } else {
                    task.setCriticalRatio(0.0); // 已经逾期
                }
            } else {
                task.setCriticalRatio(1.0); // 无截止时间，设为中等
            }

            // 2. 计算紧急度评分（基于优先级和关键比率）
            double urgencyScore = calculateUrgencyScore(task);
            task.setUrgencyScore(urgencyScore);

            // 3. 计算SPT评分（处理时间越短评分越高）
            double sptScore = 1.0 - (double) task.getTotalProcessingTime() / maxProcessingTime;
            task.setSptScore(sptScore);

            // 4. 计算关键路径评分（基于工序数量和复杂度）
            double criticalPathScore = calculateCriticalPathScore(task);
            task.setCriticalPathScore(criticalPathScore);

            // 5. 计算综合评分（加权平均）
            double compositeScore =
                    urgencyScore * 0.4 +        // 紧急度权重40%
                            sptScore * 0.2 +            // SPT权重20%
                            criticalPathScore * 0.3 +   // 关键路径权重30%
                            (task.getCriticalRatio() < 1.0 ? 0.1 : 0.0); // 逾期风险加成10%

            task.setCompositeScore(compositeScore);

            log.debug("任务 {} - 紧急度: {:.3f}, SPT: {:.3f}, 关键路径: {:.3f}, 综合: {:.3f}",
                    task.getWorkOrder().getWorkOrderId(), urgencyScore, sptScore, criticalPathScore, compositeScore);
        }

        log.info("关键路径和SPT评分计算完成");
    }

    /**
     * 计算紧急度评分
     */
    private double calculateUrgencyScore(TaskInfo task) {
        // 基于优先级的基础评分
        double priorityScore = 1.0 - (task.getPriority() - 1) * 0.2; // 优先级1=1.0, 2=0.8, 3=0.6...

        // 基于关键比率的调整
        double criticalRatioBonus = 0.0;
        if (task.getCriticalRatio() < 0.5) {
            criticalRatioBonus = 0.3; // 非常紧急
        } else if (task.getCriticalRatio() < 1.0) {
            criticalRatioBonus = 0.1; // 比较紧急
        }

        return Math.min(1.0, priorityScore + criticalRatioBonus);
    }

    /**
     * 计算关键路径评分
     */
    private double calculateCriticalPathScore(TaskInfo task) {
        List<Operation> operations = task.getOperations();

        // 基于工序数量的复杂度
        double complexityScore = Math.min(1.0, operations.size() / 10.0);

        // 基于工序依赖关系的关键性
        double dependencyScore = 0.0;
        for (Operation op : operations) {
            if (op.getPredecessorOps() != null && !op.getPredecessorOps().trim().isEmpty()) {
                dependencyScore += 0.1; // 每个依赖增加0.1分
            }
        }
        dependencyScore = Math.min(1.0, dependencyScore);

        // 基于处理时间的影响
        double timeImpactScore = Math.min(1.0, task.getTotalProcessingTime() / 480.0); // 8小时为满分

        return (complexityScore * 0.4 + dependencyScore * 0.4 + timeImpactScore * 0.2);
    }

    /**
     * 执行混合调度策略
     */
    private List<ProductionTask> executeHybridScheduling(
            List<TaskInfo> taskInfos,
            MultiValueMap<String, Tuple2<LocalDateTime, LocalDateTime>> machineAvailableTime,
            LocalDateTime scheduleStartTime) {

        log.debug("执行关键路径+SPT混合调度策略");

        List<ProductionTask> allTasks = new ArrayList<>();
        AtomicInteger taskSequence = new AtomicInteger(1);

        // 按综合评分排序（评分高的优先）
        taskInfos.sort((t1, t2) -> Double.compare(t2.getCompositeScore(), t1.getCompositeScore()));

        // 记录前5个最高分任务
        log.info("=== 关键路径+SPT调度优先级 ===");
        for (int i = 0; i < Math.min(5, taskInfos.size()); i++) {
            TaskInfo task = taskInfos.get(i);
            log.info("第{}位: 工单 {} (综合评分: {:.3f}, 处理时间: {}分钟)",
                    i + 1, task.getWorkOrder().getWorkOrderId(),
                    task.getCompositeScore(), task.getTotalProcessingTime());
        }

        // 按优先级顺序处理任务
        for (TaskInfo taskInfo : taskInfos) {
            try {
                List<ProductionTask> orderTasks = createTasksForWorkOrder(
                        taskInfo, machineAvailableTime, scheduleStartTime, taskSequence);
                allTasks.addAll(orderTasks);

                log.debug("工单 {} 生成了 {} 个任务",
                        taskInfo.getWorkOrder().getWorkOrderId(), orderTasks.size());
            } catch (Exception e) {
                log.error("为工单 {} 生成任务失败", taskInfo.getWorkOrder().getWorkOrderId(), e);
            }
        }

        log.info("混合调度策略完成，总任务数: {}", allTasks.size());
        return allTasks;
    }

    /**
     * 为任务信息创建生产任务（复用CombineAlgorithm的时间管理逻辑）
     */
    private List<ProductionTask> createTasksForWorkOrder(
            TaskInfo taskInfo,
            MultiValueMap<String, Tuple2<LocalDateTime, LocalDateTime>> machinesAvailableTime,
            LocalDateTime scheduleStartTime,
            AtomicInteger taskSequence) {

        List<ProductionTask> tasks = new ArrayList<>();
        WorkOrder workOrder = taskInfo.getWorkOrder();
        List<Operation> operations = taskInfo.getOperations();
        Integer productQuantity = workOrder.getQuantity();

        // 遍历工序生成任务
        LocalDateTime predecessorOpEndTime = LocalDateTime.MIN;
        for (Operation operation : operations) {
            // 处理前置工序
            if (operation.getPredecessorOps() != null) {
                String[] predecessorOps = operation.getPredecessorOps().split(",");
                for (String predecessorOpId : predecessorOps) {
                    Optional<ProductionTask> predTask = tasks.stream()
                            .filter(task -> Objects.equals(task.getOperationId(), predecessorOpId))
                            .findFirst();

                    if (predTask.isPresent()) {
                        LocalDateTime currentTime = predTask.get().getPlanEndTime();
                        if (currentTime.isAfter(predecessorOpEndTime)) {
                            predecessorOpEndTime = currentTime;
                        }
                    }
                }
            }

            // 找到需要的机器类型
            String machineTypeId = operation.getMachineTypeId();
            List<Machine> machines = scheduleDataService.getMachinesByType(machineTypeId);

            // 使用关键路径+SPT的机器选择策略
            String selectedMachineId = null;
            Tuple2<LocalDateTime, LocalDateTime> selectedInterval = null;

            for (Machine machine : machines) {
                // 计算任务的生产时间
                double machineCapacity = machine.getMaxCapacity().doubleValue();
                double hoursRequired = productQuantity / machineCapacity;
                double halfHourUnits = Math.ceil(hoursRequired * 2);
                double totalHours = halfHourUnits * 0.5;
                Duration duration = Duration.ofMinutes((long) (totalHours * 60));

                // 找到当前机器的负载情况
                String machineId = machine.getMachineId();
                List<Tuple2<LocalDateTime, LocalDateTime>> freeTimes = machinesAvailableTime.get(machineId);
                freeTimes.sort(Comparator.comparing(Tuple2::getFirst));

                // 遍历所有时间段进行插入，找到最早能排产的时间段
                for (Tuple2<LocalDateTime, LocalDateTime> freeTime : freeTimes) {
                    LocalDateTime freeStart = freeTime.getFirst();
                    LocalDateTime freeEnd = freeTime.getSecond();

                    // 如果前置工序的结束时间在当前free时间段之后，则无法分配
                    if (freeEnd.isBefore(predecessorOpEndTime)) continue;

                    // 如果空闲时间的开始在前置工序结束时间之前，时间段应是[predOpEndTime, freeEnd]
                    if (freeStart.isBefore(predecessorOpEndTime)) {
                        freeStart = predecessorOpEndTime;
                    }

                    // 计算free时间
                    Duration freeDuration;
                    if (freeEnd.equals(LocalDateTime.MAX)) {
                        freeDuration = Duration.ofSeconds(Long.MAX_VALUE);
                    } else {
                        freeDuration = Duration.between(freeStart, freeEnd);
                    }

                    // 如果能插入
                    if (freeDuration.compareTo(duration) >= 0) {
                        LocalDateTime taskEnd = freeStart.plusMinutes(duration.toMinutes());
                        Tuple2<LocalDateTime, LocalDateTime> allocateInterval = new Tuple2<>(freeStart, taskEnd);

                        // 关键路径+SPT机器选择策略：优先选择最早完成的机器
                        if (selectedMachineId == null) {
                            selectedMachineId = machineId;
                            selectedInterval = allocateInterval;
                        } else if (taskEnd.isBefore(selectedInterval.getSecond())) {
                            selectedMachineId = machineId;
                            selectedInterval = allocateInterval;
                        } else if (taskEnd.isEqual(selectedInterval.getSecond())) {
                            // 结束时间相同时选择开始时间晚的（更紧凑）
                            if (freeStart.isAfter(selectedInterval.getFirst())) {
                                selectedMachineId = machineId;
                                selectedInterval = allocateInterval;
                            }
                        }
                        break; // 当前机器已经找到，继续下个机器
                    }
                }
            }

            // 生成任务
            if (selectedMachineId != null && selectedInterval != null) {
                ProductionTask task = new ProductionTask();
                String timeStamp = String.valueOf(System.currentTimeMillis()).substring(7);
                Duration productDuration = Duration.between(selectedInterval.getFirst(), selectedInterval.getSecond());

                task.setTaskId("CPM_SPT_" + timeStamp + String.format("%03d", taskSequence.getAndIncrement()));
                task.setWorkOrderId(workOrder.getWorkOrderId());
                task.setOperationId(operation.getOperationId());
                task.setMachineId(selectedMachineId);
                task.setQuantity(productQuantity);
                task.setStatus("已分配");
                task.setStandardTime((int) productDuration.toMinutes());
                task.setPlannedTime((int) productDuration.toMinutes());
                task.setPlanStartTime(selectedInterval.getFirst());
                task.setPlanEndTime(selectedInterval.getSecond());
                task.setCreateTime(LocalDateTime.now());
                task.setUpdateTime(LocalDateTime.now());

                tasks.add(task);

                // 更新机器空闲时间表
                updateMachineAvailableTime(machinesAvailableTime, selectedMachineId, selectedInterval);

                log.debug("关键路径任务分配: 工单 {} 工序 {} → 机器 {} ({} - {})",
                        workOrder.getWorkOrderId(), operation.getOperationId(),
                        selectedMachineId, selectedInterval.getFirst(), selectedInterval.getSecond());
            }
        }

        return tasks;
    }

    /**
     * 更新机器空闲时间表（复用CombineAlgorithm逻辑）
     */
    private void updateMachineAvailableTime(
            MultiValueMap<String, Tuple2<LocalDateTime, LocalDateTime>> machinesAvailableTime,
            String machineId,
            Tuple2<LocalDateTime, LocalDateTime> usedInterval) {

        LocalDateTime taskStart = usedInterval.getFirst();
        LocalDateTime taskEnd = usedInterval.getSecond();

        List<Tuple2<LocalDateTime, LocalDateTime>> machineFreeTime = machinesAvailableTime.get(machineId);
        Iterator<Tuple2<LocalDateTime, LocalDateTime>> iterator = machineFreeTime.iterator();
        List<Tuple2<LocalDateTime, LocalDateTime>> newSlots = new ArrayList<>();

        while (iterator.hasNext()) {
            Tuple2<LocalDateTime, LocalDateTime> slot = iterator.next();
            LocalDateTime slotStart = slot.getFirst();
            LocalDateTime slotEnd = slot.getSecond();

            if (!taskStart.isBefore(slotStart) && !taskEnd.isAfter(slotEnd)) {
                iterator.remove();

                if (slotStart.isBefore(taskStart)) {
                    newSlots.add(new Tuple2<>(slotStart, taskStart));
                }

                if (taskEnd.isBefore(slotEnd)) {
                    newSlots.add(new Tuple2<>(taskEnd, slotEnd));
                }

                break;
            }
        }

        machineFreeTime.addAll(newSlots);
        machineFreeTime.sort(Comparator.comparing(Tuple2::getFirst));
    }

    /**
     * 获取机器空闲时间表（使用CombineAlgorithm的高级时间管理）
     */
    private MultiValueMap<String, Tuple2<LocalDateTime, LocalDateTime>> getMachineAvailableTime(LocalDateTime scheduleStartTime) {
        return machineLoadService.getCurrentMachineAvailablePeriod(scheduleStartTime);
    }

    private List<ScheduleDetail> generateScheduleDetails(List<ProductionTask> productionTasks) {
        List<ScheduleDetail> details = new ArrayList<>();
        AtomicInteger sequence = new AtomicInteger(1);
        String timeStamp = String.valueOf(System.currentTimeMillis()).substring(7);

        for (ProductionTask task : productionTasks) {
            ScheduleDetail detail = new ScheduleDetail();
            detail.setDetailId("CPM_SPT_DETAIL_" + timeStamp + String.format("%03d", sequence.getAndIncrement()));
            detail.setTaskId(task.getTaskId());
            detail.setMachineId(task.getMachineId());
            detail.setScheduledStartTime(task.getPlanStartTime());
            detail.setScheduledEndTime(task.getPlanEndTime());
            detail.setSequenceNo(sequence.get());
            detail.setCreateTime(LocalDateTime.now());

            details.add(detail);
        }

        return details;
    }

    private LocalDateTime calculateScheduleEndTime(List<ProductionTask> productionTasks) {
        return productionTasks.stream()
                .map(ProductionTask::getPlanEndTime)
                .filter(Objects::nonNull)
                .max(LocalDateTime::compareTo)
                .orElse(LocalDateTime.now());
    }

    private int calculateMachineCount(List<ProductionTask> productionTasks) {
        return (int) productionTasks.stream()
                .map(ProductionTask::getMachineId)
                .filter(Objects::nonNull)
                .distinct()
                .count();
    }
} 